package cn.yuanqiao.web.controller.auth;

import cn.yuanqiao.auth.service.ApiRequestService;
import cn.yuanqiao.auth.util.Sm4Utils;
import cn.yuanqiao.auth.util.TokenParamUtil;
import cn.yuanqiao.common.constant.SecurityConstants;
import cn.yuanqiao.common.core.domain.AjaxResult;
import cn.yuanqiao.common.core.domain.R;

import cn.yuanqiao.common.core.domain.entity.SysDept;
import cn.yuanqiao.common.core.domain.entity.SysUser;
import cn.yuanqiao.common.core.domain.model.LoginUser;
import cn.yuanqiao.common.exception.ServiceException;
import cn.yuanqiao.common.utils.DateUtils;
import cn.yuanqiao.framework.web.service.TokenService;
import cn.yuanqiao.system.service.ISysDeptService;
import cn.yuanqiao.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;


/**
 * @ClassName: SingleSignOnController
 * @Description: 类的描述
 * @author: lihuahua
 * @date: 2023/11/20 10:22
 * @Blog: huahuacoco.top
 */
@RestController
@RequestMapping("/auth/ssoLogin")
public class SingleSignOnController {


    @Resource
    private TokenService tokenService;

    @Autowired
    private ApiRequestService apiRequestService;

    @Resource
    private ISysDeptService remoteSysDeptService;

    @Resource
    private ISysUserService remoteUserService;


    private static final Logger log = LoggerFactory.getLogger(SingleSignOnController.class);

    private final String login = "login";
    private final String pullTask = "pullTask";
    private final String pullFinish = "pullFinish";
    private final String logout = "logout";


    @GetMapping("/getSingleSignOn")
    public AjaxResult getSingleSignOn() {
        Map<String,Object> result = new HashMap<>();
        result.put("singleSignOn", TokenParamUtil.isSingleSignOn());
        result.put("clientId",TokenParamUtil.getClientId());
        result.put("OAuthPath",TokenParamUtil.getOAuthPath());
        result.put("redirectPath",TokenParamUtil.getRedirectPath());
        result.put("redirectPathPhone",TokenParamUtil.getRedirectPathPhone());
        return AjaxResult.success(result);
    }

    @PostMapping("/singleSignOn")
    public R<?> singleSignOn(@RequestParam("code") String code) throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException,ServiceException {
        String tenantCode = TokenParamUtil.getDefaultTenant();
        //调用验证token的方法
        Map<String,Object> tokenMap = apiRequestService.getAccessToken(code);
        //校验返回数据
        apiRequestService.checkResultMapIsQualified(tokenMap,"错误:获取AccessToken失败");
        String accessToken = String.valueOf(tokenMap.get("access_token"));
        String expiresIn = String.valueOf(tokenMap.get("expires_in"));
        String refreshToken = String.valueOf(tokenMap.get("refresh_token"));
        String uid = String.valueOf(tokenMap.get("uid"));
        Map<String, Object> userInfoMap = apiRequestService.getUserInfo(accessToken, uid);
        //校验返回数据
        apiRequestService.checkResultMapIsQualified(userInfoMap,"错误:获取userInfo失败");
        LoginUser loginName = remoteUserService.getUserInfo(String.valueOf(userInfoMap.get("loginName")), tenantCode);
        loginName.setToken(accessToken);
        Map<String, Object> serviceToken = tokenService.createTokenSingle(loginName,"tenant",Long.valueOf(expiresIn));
        serviceToken.put("accessToken",accessToken);
        serviceToken.put("refreshToken",refreshToken);
        return R.ok(serviceToken);
    }


    /**
     * 同步最新的一条数据
     * @return 是否同步成功
     * @throws NoSuchAlgorithmException
     * @throws KeyStoreException
     * @throws KeyManagementException
     * @throws ServiceException
     */
    @PostMapping("/AsyncLatestTask")
    public R<String> AsyncLatestTask() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException, ServiceException {
        String tenantCode = TokenParamUtil.getDefaultTenant();
        Map<String, Object> pullTokenData = apiRequestService.unifyIdentityManageRequest(login,null,null,null,null,null);
        log.info("获取Token："+pullTokenData.toString());
        String tokenId = String.valueOf(pullTokenData.get("tokenId"));
        String taskId = null;
        Sm4Utils sm4Utils = new Sm4Utils();
        Boolean successFlag = false;
        String failMessage = null;
        int success = 0;
        try{
            Map<String, Object> pullTaskData = apiRequestService.unifyIdentityManageRequest(pullTask,tokenId,null,null,null,null);
            log.info("拉取数据："+pullTaskData.toString());
            taskId = String.valueOf(pullTaskData.get("taskId"));
            Long guid = pullTaskData.get("guid") == null?null:Long.valueOf(pullTaskData.get("guid").toString());
            String oneId = pullTaskData.get("id") == null?null:String.valueOf(pullTaskData.get("id"));
            //区分是用户、目标机构还是目标账户  目标账号： TARGET_ACCOUNT   目标机构：TARGET_ORGANIZATION
            String objectType = String.valueOf(pullTaskData.get("objectType"));
            Map<String,Object> dataMap = (Map<String, Object>) pullTaskData.get("data");
            //包含CREATE（创建）、DISABLED（禁用）、DELETED（删除）、ENABLED（启用）、UPDATED（更新）
            String effectOn = String.valueOf(pullTaskData.get("effectOn"));

            if ("TARGET_ORGANIZATION".equals(objectType)){
                //目标机构
                SysDept sysDept = new SysDept();
                sysDept.setDeptId(guid);
                sysDept.setOneId(String.valueOf(dataMap.get("systemOrgId")));
                sysDept.setTenantCode(tenantCode);
                sysDept.setDeptName(String.valueOf(dataMap.get("fullname")));
                sysDept.setEmail(String.valueOf(dataMap.get("email")));
                sysDept.setPhone(String.valueOf(dataMap.get("tel")));
                Long parentId = 100L;
                String ancestors = "0,100";
                if (dataMap.get("_parent")!=null){
                    boolean isDeptId = String.valueOf(dataMap.get("_parent")).matches("^[0-9]*$");
                    SysDept parent = null;
                    if (isDeptId){
                        parent = remoteSysDeptService.selectDeptById(Long.valueOf(String.valueOf(dataMap.get("_parent"))));
                    }else {
                        SysDept sysDeptQuery = new SysDept();
                        sysDeptQuery.setDeptName(String.valueOf(dataMap.get("_parent")));
                        sysDeptQuery.setTenantCode(tenantCode);
                        parent = remoteSysDeptService.selectDeptList(sysDeptQuery).get(0);
                    }
                    parentId = parent.getDeptId();
                    ancestors = parent.getAncestors()+","+parentId;
                }
                sysDept.setParentId(parentId);
                sysDept.setStatus((Boolean)dataMap.get("isDisabled")?"1":"0");
                sysDept.setDelFlag("0");
                sysDept.setAncestors(ancestors);
                sysDept.setCreateBy("AsyncSystem");
                sysDept.setCreateTime(DateUtils.dateTime("yyyy-MM-dd HH:mm:ss",String.valueOf(dataMap.get("createAt"))));
                sysDept.setUpdateBy("AsyncSystem");
                sysDept.setUpdateTime(DateUtils.dateTime("yyyy-MM-dd HH:mm:ss",String.valueOf(dataMap.get("updateAt"))));
                R<Integer> integerR = null;
                if ("CREATED".equals(effectOn)){
                    R<SysDept> sysDeptR = remoteSysDeptService.addAsync(sysDept);
                    integerR = sysDeptR!=null&&sysDeptR.getData()!=null? R.ok(Integer.valueOf(1)): R.fail(sysDeptR.getMsg());
                    guid = sysDeptR.getData().getDeptId();
                }else if ("DISABLED".equals(effectOn)||"ENABLED".equals(effectOn)||"UPDATED".equals(effectOn)){
                    integerR = remoteSysDeptService.editAsync(sysDept);
                }else if ("DELETED".equals(effectOn)){
                    integerR = remoteSysDeptService.removeAsync(sysDept.getDeptId());
                }
                successFlag = integerR!=null&&integerR.getData()!=null&&integerR.getData()>0?true:false;
                failMessage = integerR.getMsg();
            }else if ("TARGET_ACCOUNT".equals(objectType)){
                //目标账户
                SysUser sysUser = new SysUser();
                sysUser.setUserId(guid);
                sysUser.setOneId(String.valueOf(dataMap.get("systemUserId")));
                sysUser.setTenantCode(tenantCode);
                sysUser.setUserName(String.valueOf(dataMap.get("username")));
                sysUser.setNickName(String.valueOf(dataMap.get("fullname")));
                sysUser.setSex(String.valueOf(dataMap.get("sex")));
                String mobile = null;
                if (dataMap.get("mobile")!=null){
                    try {
                        mobile = sm4Utils.decryptData_ECB(String.valueOf(dataMap.get("mobile")), "JLB6L6MJVIT5Z7IL");
                    }catch (Exception e){
                        log.info("ID为"+guid+"的用户电话号码解密失败，请注意处理");
                        mobile = String.valueOf(dataMap.get("mobile"));
                        e.printStackTrace();
                    }
                }
                sysUser.setPhonenumber(mobile);
                sysUser.setPassword(dataMap.get("password")==null?null:String.valueOf(dataMap.get("password")));
                sysUser.setStatus((Boolean)dataMap.get("isDisabled")?"1":"0");
                sysUser.setDeptId(Long.valueOf(dataMap.get("_organization").toString()));
                sysUser.setDelFlag("0");
                sysUser.setDept(remoteSysDeptService.selectDeptById(sysUser.getDeptId()));
                sysUser.setCreateBy("AsyncSystem");
                sysUser.setCreateTime(DateUtils.dateTime("yyyy-MM-dd HH:mm:ss",String.valueOf(dataMap.get("createAt"))));
                sysUser.setUpdateBy("AsyncSystem");
                sysUser.setUpdateTime(DateUtils.dateTime("yyyy-MM-dd HH:mm:ss",String.valueOf(dataMap.get("updateAt"))));
                R<Integer> integerR = null;
                if ("CREATED".equals(effectOn)){
                    R<SysUser> sysUserR = remoteUserService.addAsync(sysUser);
                    integerR = sysUserR!=null&&sysUserR.getData()!=null? R.ok(Integer.valueOf(1)): R.fail(sysUserR.getMsg());
                    guid = sysUserR.getData().getUserId();
                }else if ("DISABLED".equals(effectOn)||"ENABLED".equals(effectOn)||"UPDATED".equals(effectOn)){
                    integerR = remoteUserService.editAsync(sysUser);
                }else if ("DELETED".equals(effectOn)){
                    integerR = remoteUserService.removeAsync(sysUser.getUserId());
                }
                successFlag = integerR!=null&&integerR.getData()!=null&&integerR.getData()>0?true:false;
                failMessage = integerR.getMsg();
            }
            if (successFlag){
                success++;
                Map<String, Object> pullFinishMap = apiRequestService.unifyIdentityManageRequest(pullFinish, tokenId, taskId, guid, successFlag, failMessage);
                log.info("拉取完成信息（成功）："+pullFinishMap.toString());
            }

            Map<String, Object> logoutMap = apiRequestService.unifyIdentityManageRequest(logout, tokenId, null, null, null, null);
            log.info("登出信息（成功）："+logoutMap.toString());
        }catch (Exception e){
            Map<String, Object> pullFinishMap = apiRequestService.unifyIdentityManageRequest(pullFinish, tokenId, taskId, null, false,"同步数据失败："+ e.getMessage());
            log.info("拉取完成信息（失败）："+pullFinishMap.toString());
            Map<String, Object> logoutMap = apiRequestService.unifyIdentityManageRequest(logout, tokenId, null, null, null, null);
            log.info("登出信息（失败）："+logoutMap.toString());
            if ("请求统一身份管理接口pullTask方法失败：没有返回数据".equals(e.getMessage())){
                //没有等待推送的数据
                failMessage = success == 0 ? "没有等待推送的数据":"成功同步了"+success+"条数据";
                System.out.println("没有等待推送的数据");
            }else {
                throw e;
            }
        }
        return successFlag? R.ok("任务完成，推送了"+success+"条数据"): R.fail(failMessage);
    }


    /**
     * 同步最新的一条数据
     * @return 是否同步成功
     * @throws NoSuchAlgorithmException
     * @throws KeyStoreException
     * @throws KeyManagementException
     * @throws ServiceException
     */
    @PostMapping("/AsyncAllTask")
    public R<String> AsyncAllTask() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException,ServiceException {
        String tenantCode = TokenParamUtil.getDefaultTenant();
        Map<String, Object> pullTokenData = apiRequestService.unifyIdentityManageRequest(login,null,null,null,null,null);
        log.info("获取token："+pullTokenData.toString());
        String tokenId = String.valueOf(pullTokenData.get("tokenId"));
        String taskId = null;
        Sm4Utils sm4Utils = new Sm4Utils();
        Boolean successFlag = false;
        String failMessage = null;
        int success = 0 ;
        try{
            //提供进入循环的值
            successFlag = true;
            while (successFlag){
                //进入后重置值，保证默认值为false
                successFlag = false;
                Map<String, Object> pullTaskData = apiRequestService.unifyIdentityManageRequest(pullTask,tokenId,null,null,null,null);
                log.info("拉取数据："+pullTaskData.toString());
                taskId = String.valueOf(pullTaskData.get("taskId"));
                Long guid = pullTaskData.get("guid") == null?null:Long.valueOf(pullTaskData.get("guid").toString());
                String oneId = pullTaskData.get("id") == null?null:String.valueOf(pullTaskData.get("id"));
                //区分是用户、目标机构还是目标账户  目标账号： TARGET_ACCOUNT   目标机构：TARGET_ORGANIZATION
                String objectType = String.valueOf(pullTaskData.get("objectType"));
                Map<String,Object> dataMap = (Map<String, Object>) pullTaskData.get("data");
                //包含CREATE（创建）、DISABLED（禁用）、DELETED（删除）、ENABLED（启用）、UPDATED（更新）
                String effectOn = String.valueOf(pullTaskData.get("effectOn"));

                if ("TARGET_ORGANIZATION".equals(objectType)){
                    //目标机构
                    SysDept sysDept = new SysDept();
                    sysDept.setDeptId(guid);
                    sysDept.setOneId(String.valueOf(dataMap.get("systemOrgId")));
                    sysDept.setTenantCode(tenantCode);
                    sysDept.setDeptName(String.valueOf(dataMap.get("fullname")));
                    sysDept.setEmail(String.valueOf(dataMap.get("email")));
                    sysDept.setPhone(String.valueOf(dataMap.get("tel")));
                    Long parentId = 100L;
                    String ancestors = "0,100";
                    if (dataMap.get("_parent")!=null){
                        boolean isDeptId = String.valueOf(dataMap.get("_parent")).matches("^[0-9]*$");
                        SysDept parent = null;
                        if (isDeptId){
                            parent = remoteSysDeptService.selectDeptById(Long.valueOf(String.valueOf(dataMap.get("_parent"))));
                        }else {
                            SysDept sysDeptQuery = new SysDept();
                            sysDeptQuery.setDeptName(String.valueOf(dataMap.get("_parent")));
                            sysDeptQuery.setTenantCode(tenantCode);
                            parent = remoteSysDeptService.selectDeptList(sysDeptQuery).get(0);
                        }
                        parentId = parent.getDeptId();
                        ancestors = parent.getAncestors()+","+parentId;
                    }
                    sysDept.setParentId(parentId);
                    sysDept.setStatus((Boolean)dataMap.get("isDisabled")?"1":"0");
                    sysDept.setDelFlag("0");
                    sysDept.setAncestors(ancestors);
                    sysDept.setCreateBy("AsyncSystem");
                    sysDept.setCreateTime(DateUtils.dateTime("yyyy-MM-dd HH:mm:ss",String.valueOf(dataMap.get("createAt"))));
                    sysDept.setUpdateBy("AsyncSystem");
                    sysDept.setUpdateTime(DateUtils.dateTime("yyyy-MM-dd HH:mm:ss",String.valueOf(dataMap.get("updateAt"))));
                    R<Integer> integerR = null;
                    if ("CREATED".equals(effectOn)){
                        R<SysDept> sysDeptR = remoteSysDeptService.addAsync(sysDept);
                        integerR = sysDeptR!=null&&sysDeptR.getData()!=null? R.ok(Integer.valueOf(1)): R.fail(sysDeptR.getMsg());
                        guid = sysDeptR.getData().getDeptId();
                    }else if ("DISABLED".equals(effectOn)||"ENABLED".equals(effectOn)||"UPDATED".equals(effectOn)){
                        integerR = remoteSysDeptService.editAsync(sysDept);
                    }else if ("DELETED".equals(effectOn)){
                        integerR = remoteSysDeptService.removeAsync(sysDept.getDeptId());
                    }
                    successFlag = integerR!=null&&integerR.getData()!=null&&integerR.getData()>0?true:false;
                    failMessage = integerR.getMsg();
                }else if ("TARGET_ACCOUNT".equals(objectType)){
                    //目标账户
                    SysUser sysUser = new SysUser();
                    sysUser.setUserId(guid);
                    sysUser.setOneId(String.valueOf(dataMap.get("systemUserId")));
                    sysUser.setTenantCode(tenantCode);
                    sysUser.setUserName(String.valueOf(dataMap.get("username")));
                    sysUser.setNickName(String.valueOf(dataMap.get("fullname")));
                    sysUser.setSex(String.valueOf(dataMap.get("sex")));
                    String mobile = null;
                    if (dataMap.get("mobile")!=null){
                        try {
                            mobile = sm4Utils.decryptData_ECB(String.valueOf(dataMap.get("mobile")), "JLB6L6MJVIT5Z7IL");
                        }catch (Exception e){
                            log.info("ID为"+guid+"的用户电话号码解密失败，请注意处理");
                            mobile = String.valueOf(dataMap.get("mobile"));
                            e.printStackTrace();
                        }
                    }
                    sysUser.setPhonenumber(mobile);
                    sysUser.setPassword(dataMap.get("password")==null?null:String.valueOf(dataMap.get("password")));
                    sysUser.setStatus((Boolean)dataMap.get("isDisabled")?"1":"0");
                    sysUser.setDeptId(Long.valueOf(dataMap.get("_organization").toString()));
                    sysUser.setDelFlag("0");
                    sysUser.setDept(remoteSysDeptService.selectDeptById(sysUser.getDeptId()));
                    sysUser.setCreateBy("AsyncSystem");
                    sysUser.setCreateTime(DateUtils.dateTime("yyyy-MM-dd HH:mm:ss",String.valueOf(dataMap.get("createAt"))));
                    sysUser.setUpdateBy("AsyncSystem");
                    sysUser.setUpdateTime(DateUtils.dateTime("yyyy-MM-dd HH:mm:ss",String.valueOf(dataMap.get("updateAt"))));
                    R<Integer> integerR = null;
                    if ("CREATED".equals(effectOn)){
                        R<SysUser> sysUserR = remoteUserService.addAsync(sysUser);
                        integerR = sysUserR!=null&&sysUserR.getData()!=null? R.ok(Integer.valueOf(1)): R.fail(sysUserR.getMsg());
                        guid = sysUserR.getData().getUserId();
                    }else if ("DISABLED".equals(effectOn)||"ENABLED".equals(effectOn)||"UPDATED".equals(effectOn)){
                        integerR = remoteUserService.editAsync(sysUser);
                    }else if ("DELETED".equals(effectOn)){
                        integerR = remoteUserService.removeAsync(sysUser.getUserId());
                    }
                    successFlag = integerR!=null&&integerR.getData()!=null&&integerR.getData()>0?true:false;
                    failMessage = integerR.getMsg();
                }
                if (successFlag){
                    //只有捕获数据的情况下才继续标识
                    success ++;
                    Map<String, Object> pullFinishMap = apiRequestService.unifyIdentityManageRequest(pullFinish, tokenId, taskId, guid, successFlag, failMessage);
                    log.info("拉取完成（成功）："+pullFinishMap.toString());
                }
            }
            //循环结束调用登出接口，注销token
            Map<String, Object> logoutMap = apiRequestService.unifyIdentityManageRequest(logout, tokenId, null, null, null, null);
            log.info("登出（成功）："+logoutMap.toString());
        }catch (Exception e){
            //apiRequestService.unifyIdentityManageRequest(pullFinish, tokenId, taskId, null, false, e.getMessage());
            //一旦出现异常，优先注销，查看是否为空任务，空任务就正常返回，否则抛出
            Map<String, Object> logoutMap = apiRequestService.unifyIdentityManageRequest(logout, tokenId, null, null, null, null);
            log.info("登出（失败）："+logoutMap.toString());
            if ("请求统一身份管理接口pullTask方法失败：没有返回数据".equals(e.getMessage())){
                //没有等待推送的数据
                failMessage = success==0?"没有等待推送的数据":"成功推送了"+success+"条数据";
                System.out.println("没有等待推送的数据");
            }else {
                throw e;
            }
        }
        return success!=0&&failMessage.equals("没有等待推送的数据")? R.ok("成功推送了"+success+"条数据"): R.fail(failMessage);
    }

}
